﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace Marmat.Forms
{
    public sealed class ControlPaintEx
    {
        private ControlPaintEx()
        {
        }

        public static void DrawCheckedFlag(Graphics g, Rectangle rect, Color color)
        {
            var points = new PointF[3];
            points[0] = new PointF(rect.X + rect.Width / 4.5f, rect.Y + rect.Height / 2.5f);
            points[1] = new PointF(rect.X + rect.Width / 2.5f, rect.Bottom - rect.Height / 3.0f);
            points[2] = new PointF(rect.Right - rect.Width / 4.0f, rect.Y + rect.Height / 4.5f);
            using (var pen = new Pen(color, 2.0f))
            {
                g.DrawLines(pen, points);
            }
        }

        public static void DrawGlass(Graphics g, RectangleF glassRect, int alphaCenter, int alphaSurround)
        {
            DrawGlass(g, glassRect, Color.White, alphaCenter, alphaSurround);
        }

        public static void DrawGlass(Graphics g, RectangleF glassRect, Color glassColor, int alphaCenter, int alphaSurround)
        {
            using (var path = new GraphicsPath())
            {
                path.AddEllipse(glassRect);
                using (var brush = new PathGradientBrush(path))
                {
                    brush.CenterColor = Color.FromArgb(alphaCenter, glassColor);
                    brush.SurroundColors = new Color[] { Color.FromArgb(alphaSurround, glassColor) };
                    brush.CenterPoint = new PointF(glassRect.X + glassRect.Width / 2f, glassRect.Y + glassRect.Height / 2f);
                    g.FillPath(brush, path);
                }
            }
        }

        public static void DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect)
        {
            DrawBackgroundImage(g, backgroundImage, backColor, backgroundImageLayout, bounds, clipRect, Point.Empty, RightToLeft.No);
        }

        public static void DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset)
        {
            DrawBackgroundImage(g, backgroundImage, backColor, backgroundImageLayout, bounds, clipRect, scrollOffset, RightToLeft.No);
        }

        public static void DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft__1)
        {
            if (g is null)
            {
                throw new ArgumentNullException("g");
            }

            if (backgroundImageLayout == ImageLayout.Tile)
            {
                using (var brush = new TextureBrush(backgroundImage, WrapMode.Tile))
                {
                    if (scrollOffset != Point.Empty)
                    {
                        var transform = brush.Transform;
                        transform.Translate(scrollOffset.X, scrollOffset.Y);
                        brush.Transform = transform;
                    }

                    g.FillRectangle(brush, clipRect);
                    return;
                }
            }

            var rect = CalculateBackgroundImageRectangle(bounds, backgroundImage, backgroundImageLayout);
            if (rightToLeft__1 == RightToLeft.Yes && backgroundImageLayout == ImageLayout.None)
            {
                rect.X += clipRect.Width - rect.Width;
            }

            using (var brush2 = new SolidBrush(backColor))
            {
                g.FillRectangle(brush2, clipRect);
            }

            if (!clipRect.Contains(rect))
            {
                if (backgroundImageLayout == ImageLayout.Stretch || backgroundImageLayout == ImageLayout.Zoom)
                {
                    rect.Intersect(clipRect);
                    g.DrawImage(backgroundImage, rect);
                }
                else if (backgroundImageLayout == ImageLayout.None)
                {
                    rect.Offset(clipRect.Location);
                    var destRect = rect;
                    destRect.Intersect(clipRect);
                    var rectangle3 = new Rectangle(Point.Empty, destRect.Size);
                    g.DrawImage(backgroundImage, destRect, rectangle3.X, rectangle3.Y, rectangle3.Width, rectangle3.Height, GraphicsUnit.Pixel);
                }
                else
                {
                    var rectangle4 = rect;
                    rectangle4.Intersect(clipRect);
                    var rectangle5 = new Rectangle(new Point(rectangle4.X - rect.X, rectangle4.Y - rect.Y), rectangle4.Size);
                    g.DrawImage(backgroundImage, rectangle4, rectangle5.X, rectangle5.Y, rectangle5.Width, rectangle5.Height, GraphicsUnit.Pixel);
                }
            }
            else
            {
                var imageAttr = new ImageAttributes();
                imageAttr.SetWrapMode(WrapMode.TileFlipXY);
                g.DrawImage(backgroundImage, rect, 0, 0, backgroundImage.Width, backgroundImage.Height, GraphicsUnit.Pixel, imageAttr);
                imageAttr.Dispose();
            }
        }

        public static void DrawScrollBarTrack(Graphics g, Rectangle rect, Color begin, Color end, Orientation orientation__1)
        {
            bool bHorizontal = orientation__1 == Orientation.Horizontal;
            var mode = bHorizontal ? LinearGradientMode.Vertical : LinearGradientMode.Horizontal;
            var blend = new Blend();
            blend.Factors = new float[] { 1.0f, 0.5f, 0.0f };
            blend.Positions = new float[] { 0.0f, 0.5f, 1.0f };
            DrawGradientRect(g, rect, begin, end, begin, begin, blend, mode, true, false);
        }

        public static void DrawScrollBarThumb(Graphics g, Rectangle rect, Color begin, Color end, Color border, Color innerBorder, Orientation orientation__1, bool changeColor)
        {
            if (changeColor)
            {
                var tmp = begin;
                begin = end;
                end = tmp;
            }

            bool bHorizontal = orientation__1 == Orientation.Horizontal;
            var mode = bHorizontal ? LinearGradientMode.Vertical : LinearGradientMode.Horizontal;
            var blend = new Blend();
            blend.Factors = new float[] { 1.0f, 0.5f, 0.0f };
            blend.Positions = new float[] { 0.0f, 0.5f, 1.0f };
            if (bHorizontal)
            {
                rect.Inflate(0, -1);
            }
            else
            {
                rect.Inflate(-1, 0);
            }

            DrawGradientRoundRect(g, rect, begin, end, border, innerBorder, blend, mode, 4, RoundStyle.All, true, true);
        }

        public static void DrawScrollBarArraw(Graphics g, Rectangle rect, Color begin, Color end, Color border, Color innerBorder, Color fore, Orientation orientation__1, ArrowDirection arrowDirection, bool changeColor)
        {
            if (changeColor)
            {
                var tmp = begin;
                begin = end;
                end = tmp;
            }

            bool bHorizontal = orientation__1 == Orientation.Horizontal;
            var mode = bHorizontal ? LinearGradientMode.Vertical : LinearGradientMode.Horizontal;
            rect.Inflate(-1, -1);
            var blend = new Blend();
            blend.Factors = new float[] { 1.0f, 0.5f, 0.0f };
            blend.Positions = new float[] { 0.0f, 0.5f, 1.0f };
            DrawGradientRoundRect(g, rect, begin, end, border, innerBorder, blend, mode, 4, RoundStyle.All, true, true);
            using (var brush = new SolidBrush(fore))
            {
                RenderHelper.RenderArrowInternal(g, rect, arrowDirection, brush);
            }
        }

        public static void DrawScrollBarSizer(Graphics g, Rectangle rect, Color begin, Color end)
        {
            var blend = new Blend();
            blend.Factors = new float[] { 1.0f, 0.5f, 0.0f };
            blend.Positions = new float[] { 0.0f, 0.5f, 1.0f };
            DrawGradientRect(g, rect, begin, end, begin, begin, blend, LinearGradientMode.Horizontal, true, false);
        }

        internal static void DrawGradientRect(Graphics g, Rectangle rect, Color begin, Color end, Color border, Color innerBorder, Blend blend, LinearGradientMode mode, bool drawBorder, bool drawInnerBorder)
        {
            using (var brush = new LinearGradientBrush(rect, begin, end, mode))
            {
                brush.Blend = blend;
                g.FillRectangle(brush, rect);
            }

            if (drawBorder)
            {
                ControlPaint.DrawBorder(g, rect, border, ButtonBorderStyle.Solid);
            }

            if (drawInnerBorder)
            {
                rect.Inflate(-1, -1);
                ControlPaint.DrawBorder(g, rect, border, ButtonBorderStyle.Solid);
            }
        }

        internal static void DrawGradientRoundRect(Graphics g, Rectangle rect, Color begin, Color end, Color border, Color innerBorder, Blend blend, LinearGradientMode mode, int radios, RoundStyle roundStyle, bool drawBorder, bool drawInnderBorder)
        {
            using (var path = GraphicsPathHelper.CreatePath(rect, radios, roundStyle, true))
            {
                using (var brush = new LinearGradientBrush(rect, begin, end, mode))
                {
                    brush.Blend = blend;
                    g.FillPath(brush, path);
                }

                if (drawBorder)
                {
                    using (var pen = new Pen(border))
                    {
                        g.DrawPath(pen, path);
                    }
                }
            }

            if (drawInnderBorder)
            {
                rect.Inflate(-1, -1);
                using (var path = GraphicsPathHelper.CreatePath(rect, radios, roundStyle, true))
                {
                    using (var pen = new Pen(innerBorder))
                    {
                        g.DrawPath(pen, path);
                    }
                }
            }
        }

        internal static Rectangle CalculateBackgroundImageRectangle(Rectangle bounds, Image backgroundImage, ImageLayout imageLayout__1)
        {
            var rectangle = bounds;
            if (backgroundImage is object)
            {
                switch (imageLayout__1)
                {
                    case ImageLayout.None:
                        {
                            rectangle.Size = backgroundImage.Size;
                            return rectangle;
                        }

                    case ImageLayout.Tile:
                        {
                            return rectangle;
                        }

                    case ImageLayout.Center:
                        {
                            if (true)
                            {
                                rectangle.Size = backgroundImage.Size;
                                var size = bounds.Size;
                                if (size.Width > rectangle.Width)
                                {
                                    rectangle.X = (size.Width - rectangle.Width) / 2;
                                }

                                if (size.Height > rectangle.Height)
                                {
                                    rectangle.Y = (size.Height - rectangle.Height) / 2;
                                }

                                return rectangle;
                            }

                            break;
                        }

                    case ImageLayout.Stretch:
                        {
                            rectangle.Size = bounds.Size;
                            return rectangle;
                        }

                    case ImageLayout.Zoom:
                        {
                            if (true)
                            {
                                var size2 = backgroundImage.Size;
                                float num = bounds.Width / (float)size2.Width;
                                float num2 = bounds.Height / (float)size2.Height;
                                if (num >= num2)
                                {
                                    rectangle.Height = bounds.Height;
                                    rectangle.Width = (int)Math.Round(Math.Truncate(size2.Width * num2 + 0.5d));
                                    if (bounds.X >= 0)
                                    {
                                        rectangle.X = (bounds.Width - rectangle.Width) / 2;
                                    }

                                    return rectangle;
                                }

                                rectangle.Width = bounds.Width;
                                rectangle.Height = (int)Math.Round(Math.Truncate(size2.Height * num + 0.5d));
                                if (bounds.Y >= 0)
                                {
                                    rectangle.Y = (bounds.Height - rectangle.Height) / 2;
                                }

                                return rectangle;
                            }

                            break;
                        }
                }
            }

            return rectangle;
        }
    }
}